package com.woniuxy.woniuticket.ordermodule.controller;

import com.woniuxy.woniuticket.financemodule.entity.PayArg;
import com.woniuxy.woniuticket.movieinfomodule.dao.CinemaInfoDAO;
import com.woniuxy.woniuticket.movieinfomodule.dao.UserVipInfoDAO;
import com.woniuxy.woniuticket.movieinfomodule.service.impl.UserVipInfoServiceImp;
import com.woniuxy.woniuticket.movieticketdmodule.util.QRUtil;
import com.woniuxy.woniuticket.ordermodule.dto.CartDTO;
import com.woniuxy.woniuticket.ordermodule.dto.OrderDTO;
import com.woniuxy.woniuticket.ordermodule.service.OrderService;
import com.woniuxy.woniuticket.ordermodule.service.serviceimpl.OrderCache;
import com.woniuxy.woniuticket.ordermodule.service.serviceimpl.ViPOrder;
import com.woniuxy.woniuticket.ordermodule.socket.MyWebSocket;
import com.woniuxy.woniuticket.ordermodule.utils.OrderPriceCompareUtil;
import com.woniuxy.woniuticket.pojo.CinemaInfo;
import com.woniuxy.woniuticket.pojo.CinemaOder;
import com.woniuxy.woniuticket.pojo.UserVipInfo;
import com.woniuxy.woniuticket.pojo.UserVipInfo;
import com.woniuxy.woniuticket.pojo.UsersInfo;
import com.woniuxy.woniuticket.resultcommon.JsonResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.ResourceUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.math.BigDecimal;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by Wu xianbo on 2019/6/4
 * 订单controller
 */

@Controller
@RequestMapping("/order")
public class CinemaOrderController {

    @Value("${upload.location}")
    private String  path;

    @Autowired
    private OrderService orderService;
    @Autowired
    private OrderCache orderCache;   //redis缓存，存放未支付订单
    @Autowired
    private ViPOrder viPOrder;      //用户购买vip订单
    @Autowired
    private MyWebSocket myWebSocket;  //websocket
    @Resource
    private CinemaInfoDAO cinemaInfoDAO;  //影院信息dao，用于查询影院logo

    @Resource
    private UserVipInfoServiceImp userVipInfoServiceImp;

    //创建订单(需要排片id、座次号)，该结果返回给选座大厅
    @RequestMapping("/ceateOrder")
    @ResponseBody
    public JsonResult ceateOrder(String arr,String scheduleId, HttpSession session){
        System.out.println("提交选座订单：座位"+arr+"排片:"+scheduleId);
        //订单中封装用户的userinfoid
        Object obj = session.getAttribute("user");
        if(obj==null){
            return  JsonResult.error("请先登录");
        }
        UsersInfo usersInfo = (UsersInfo) obj;
        Integer userinfoId = usersInfo.getId();  //封装userinfoid
        //用户创建订单时先检查有没有未支付订单,需要获取userinfoid
        List<OrderDTO> orderDTOS = orderCache.selectOrderBykey(userinfoId);
        if(orderDTOS.size()!=0){
            return JsonResult.error("您还有未支付订单");
        }
        if(arr.length()==0){
            return JsonResult.error("请选座后提交");
        }
        //创建订单dto
        CartDTO cartDTO = new CartDTO();
        //转换座位
        String[] arrs = arr.split(",");
        //拆分座位
        List<String> seatList = new ArrayList<>();
        for(int i=0;i<arrs.length;i++){
            seatList.add(arrs[i]);
        }
        cartDTO.setScheduleId(Integer.parseInt(scheduleId));  //封装排片id
        cartDTO.setSeatNumbers(seatList);                     //封装座位集合
        System.out.println("提交选座订单封装结果："+cartDTO);
        CinemaOder cinemaOder = null;
        OrderDTO orderDTO = null;
        try {

            cartDTO.setUserInfoId(userinfoId);
            //插入新订单
            cinemaOder = orderService.creatOrder(cartDTO);
            if(cinemaOder!=null){
                //查询新订单详情.从缓存中查询
                System.out.println("座位提交结果"+cinemaOder);
                orderDTO = orderCache.getOrderInfoByOrdernum(cinemaOder.getOrdernum(),userinfoId);
            }else{
                return  JsonResult.error("该座位已被占用");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return  JsonResult.error("提交失败");
        }
        return new JsonResult("提交成功",200,orderDTO);
    }

    //提交选座后查询订单详情(需要订单号和用户infoID。该controller也负责改签请求)，该请求需要在选座大厅返回一个订单号过来
    @RequestMapping("/getOrderInfo")
    public String getOrderInfo(String orderNum,Model model,HttpSession session){
        System.out.println("查询订单详情"+orderNum);
        //从session中获取userinfoid
        Object obj = session.getAttribute("user");
        Integer userInfoId = 0;
        if(obj!=null){
            UsersInfo usersInfo = (UsersInfo) obj;      //转化对象
            userInfoId = usersInfo.getId();
        }
        //从session中获取改签的订单号
        Object object = session.getAttribute("oldOrderNum");
        //如果存在旧订单号就是改签(在改签成功或取消改签时需要移除该session中的订单号)
        if(object!=null){
            System.out.println("该订单是改签");
            String oldOrderNum = (String) object;   //原订单号
            //查询原已完成订单的订单详情。
            OrderDTO oldOrderDTO = orderService.findOrderByOrderNumber(oldOrderNum);
            //存入旧订单号对应的订单详情
            model.addAttribute("oldOrderDTO",oldOrderDTO);
        }
        try {
            //从缓存中查询刚提交的订单的信息
            OrderDTO orderDTO = orderCache.getOrderInfoByOrdernum(orderNum, userInfoId);
            //存放信息到域中
            model.addAttribute("waitOrderDTO",orderDTO);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "/movieshow/waitpaying.html";
    }


    //订单支付(支付宝扫码后就请求该controller.参数1为获取的订单号,参数名称是固定的)，订单改签补差价时也调用该方法
    @RequestMapping("/payOrder")
    public void payOrder(String out_trade_no, BigDecimal total_amount,Integer vipId , HttpSession session, HttpServletResponse response) throws IOException {
        //根据订单号查询影票订单表,还是从redis缓存中查询未支付订单
        //从session中获取用户userinfoid
        Object userobj = session.getAttribute("user");
        Integer  userInfoId = 0;
        if(userobj!=null){
            UsersInfo usersInfo = (UsersInfo) userobj;      //转化对象
            userInfoId= usersInfo.getId();
        }
        //根据订单号查询影票订单表,还是从redis缓存中查询未支付订单
        OrderDTO order = orderCache.getOrderInfoByOrdernum(out_trade_no,userInfoId);
        //order为空代表是用户购买套餐，并不是买电影票
        if (order != null) {
            System.out.println("进入controller中支付订单" + out_trade_no);
            try {
                //获取session中可能存在改签订单，存在还需把原订单退票、删除
                Object obj = session.getAttribute("oldOrderNum");
                //移除session中的改签订单
                session.removeAttribute("oldOrderNum");
                //跟新数据库订单支付状态,第三个参数表示可能存在改签订单补差价，存在则需要在service中删除订单，并支付新订单
                orderService.payOrder(out_trade_no, userInfoId, obj);
            } catch (Exception e) {
                e.printStackTrace();
            }
            response.sendRedirect("/movieshow/userorder.html");
        }else{
            //该订单是用户购买vip的订单
            viPOrder.vipOrder(total_amount,1);
            //更新用户vip并插入信息
            UsersInfo usersInfo = (UsersInfo) session.getAttribute("user");
            UserVipInfo userVipInfo = new UserVipInfo();
            if(usersInfo!= null){
                userVipInfo.setUserId(usersInfo.getId());
                PayArg payinfo = (PayArg) session.getAttribute("payinfo");
                userVipInfo.setVipId(payinfo.getVipId());
                userVipInfo.setStartDate(new Date());
                userVipInfoServiceImp.changeVip(userVipInfo);
            }
            response.sendRedirect("/movieshow/userinfo.html");
        }
    }

   /*
      1:订单改签(需要原订单号、新的排片id、座位号、票数、会员折扣率)  该方法已失效，改签订单是混合在付款和退款订单中的
      2:订单退票(只需要订单号。该方法已失效，在PayController中调用的退票方法)
   */

    //用户查询订单(需要用户userinfoid和订单类型orderType)
    @RequestMapping("/findAllOrderByUid")
    @ResponseBody
    public JsonResult findAllOrderByUid(@RequestParam(value = "orderType",defaultValue = "1",required = false) Integer orderType,
                                        Model model,HttpSession session){
        //从session中移除所有改签订单的订单号
        session.removeAttribute("oldOrderNum");
        //获取影院logo
        Object logoObj = session.getAttribute("cinemaLogoImg");
        CinemaInfo cinemaInfo = null;
        if(logoObj==null){
            //查询影院logo图片
            cinemaInfo = cinemaInfoDAO.selectByPrimaryKey(1);
            //将影院logo存储到session中
            session.setAttribute("cinemaLogoImg",cinemaInfo);
        }
        //此处需要从session中获取userinfoid，如果未登录则直接返回一个空的集合回去
        //从session中获取userinfoid
        Object obj = session.getAttribute("user");
        Integer userInfoId = 0;
        if(obj!=null){
            UsersInfo usersInfo = (UsersInfo) obj;      //转化对象
            userInfoId = usersInfo.getId();
        }
        List<OrderDTO> orderDTOS = null;
        if(orderType!=0){
            //其他订单从数据库查询
            orderDTOS = orderService.findAllOrderByUid(userInfoId,orderType);
        }else{
            //未支付订单从redis缓存查询
            orderDTOS = orderCache.selectOrderBykey(userInfoId);
            System.out.println("从redis查询"+orderDTOS);
        }
        //封装影院logo
        for(OrderDTO dto:orderDTOS){
            if(cinemaInfo!=null){
                System.out.println("取之前："+cinemaInfo.getLogo());
                dto.setLogo(cinemaInfo.getLogo());
                System.out.println("取之前："+dto.getLogo());
            }
        }
        JsonResult jsonResult = new JsonResult("已付款",200,orderDTOS);
        return jsonResult;
    }

    //商家查询订单，暂时没有用到
    @RequestMapping("/findAllOrder")
    public List<OrderDTO> findAllOrder(@RequestParam(value = "page", defaultValue = "1", required = false) Integer cpage,
                                       @RequestParam(value = "limit", defaultValue = "10", required = false) Integer psize){
        return orderService.findAllOrder(cpage,psize);
    }

    //根据订单号查询订单（controller没有用到）
    @RequestMapping("/findOrderByOrderNumber")
    @ResponseBody
    public OrderDTO findOrderByOrderNumber(String orderNum){
        return orderService.findOrderByOrderNumber(orderNum);
    }

    //影票扫码获取二维码
    @RequestMapping("/getCode")
    @ResponseBody
    public JsonResult finishOrder(CinemaOder cinemaOder, HttpServletRequest request){
        String orderNum = cinemaOder.getOrdernum();     //订单号
        InetAddress addr = null;
        try {
            addr = InetAddress.getLocalHost();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            return JsonResult.error("获取二维码失败");
        }
        String ip=addr.getHostAddress().toString();    //获取本机ip
        String content = "http://"+ip+":8080/order/finishOrder?orderNum="+orderNum;  //扫描进入的controller
        //设置二维码存储路径
        String root = null;
        String codeUrl = null;
        String logopath = null;
        String codePath = null;  //返回给浏览器的地址
        try {
            //开发环境中 ：D:\projectspace\springboot05\target\classes
            //生产环境中，以jar的方式部署：D:\projectspace\springboot05\src\main\resources\static
            root = ResourceUtils.getURL("classpath:").getPath();  //项目根路径
            codePath = System.currentTimeMillis()+"";          //返回给浏览器的地址
            codeUrl = root+path+codePath;                      //二维码存放地址
            logopath = root+path+"codebglogo.jpg";             //二维码logo文件地址
            System.out.println("二维码地址："+logopath);
            QRUtil.encode(content,logopath,codeUrl,true);
        }catch (Exception e) {
            e.printStackTrace();
            return JsonResult.error("获取二维码失败");
        }
        return new JsonResult("获取二维码成功",200,"/upload/"+codePath);
    }

    //扫码之后的请求
    @RequestMapping("/finishOrder")
    public String finishOrder(String orderNum) throws IOException {
        System.out.println("二维码已被扫"+orderNum);
        //封装订单对象
        CinemaOder cinemaOder = new CinemaOder();
        cinemaOder.setOrdernum(orderNum);
        orderService.finishOrder(cinemaOder);  //更新数据库
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        //通知页面更新
        myWebSocket.sendMessage("ok");
        return "movieshow/index.html";
    }

    //用户退票时校验是否能退票
    @RequestMapping("/checkReturnCondition")
    @ResponseBody
    public JsonResult checkReturnCondition(String orderNum){
        System.out.println("校验订单是否满足退票："+orderNum);
        boolean result = orderService.checkReturnCondition(orderNum);
        if(!result){
            return JsonResult.error("该订单已过退票时间");
        }
        return JsonResult.ok();
    }

    //用户改签时校验是否满足改签
    @RequestMapping("/checkChangeCondition")
    @ResponseBody
    public JsonResult checkChangeCondition(String oldOrderNum, HttpSession session){
        System.out.println("校验订单是否满足改签"+oldOrderNum);
        boolean result = orderService.checkChangeCondition(oldOrderNum);
        if(!result){
            return JsonResult.error("该订单已过改签时间");
        }
        //在session中存放需要改签的订单号,该订单已成为旧订单号
        session.setAttribute("oldOrderNum",oldOrderNum);
        return JsonResult.ok();
    }


    //用户改签时判断是退钱、补差价还是差额为0（参数是新的订单号）该请求是在改签提交页面被请求的。waitpaying.html
    @RequestMapping("/validChangeOrder")
    @ResponseBody
    public JsonResult validChangeOrder(String neworderNum,HttpSession session){
        System.out.println("校验改签订单差价："+neworderNum);
        //获取用户id
        //从session中获取userinfoid
        Object userObj = session.getAttribute("user");
        Integer userInfoId = 0;
        if(userObj!=null){
            UsersInfo usersInfo = (UsersInfo) userObj;      //转化对象
            userInfoId = usersInfo.getId();
        }
        OrderDTO oldOrderDTO = null;
        //查询原订单详情
        Object obj = session.getAttribute("oldOrderNum");
        if(obj!=null){
            String oldorderNum = (String) obj;
            oldOrderDTO = orderService.findOrderByOrderNumber(oldorderNum);
        }
        //查询新订单(可以考虑从redis数据库查询)
        OrderDTO newOrderDTO = orderCache.getOrderInfoByOrdernum(neworderNum,userInfoId);
        //调用订单价格比较方法比较两笔订单。该对象封装了是补差价、退差价、以及差价的数量是多少
        JsonResult result = OrderPriceCompareUtil.orderPriceCompare(oldOrderDTO,newOrderDTO);
        if(result==null){
            return  JsonResult.error("改签失败");
        }
        return result;
    }

    //待支付订单从redis缓存中查询订单情况,待支付订单使用
    @RequestMapping("/getWaitPayInfoFromCache")
    @ResponseBody
    public JsonResult getWaitPayInfoFromCache(String orderNum,HttpSession session){
        //从session中获取用户userinfoid
        Object userObj = session.getAttribute("user");
        Integer userInfoId = 0;
        if(userObj!=null){
            UsersInfo usersInfo = (UsersInfo) userObj;      //转化对象
            userInfoId = usersInfo.getId();
        }
        //从缓存中查询订单详情
        OrderDTO orderDTO = orderCache.getOrderInfoByOrdernum(orderNum,userInfoId);
        return new JsonResult("未支付订单",500,orderDTO);
    }
}
